import { Request, Response, NextFunction } from 'express';
import { AuthenticatedRequest } from './authorization';
import { AuditLogService } from '../services/auditLogService';
import { AuditLogType } from '../types/auditLog';

export enum AuditLogStatus {
  SUCCESS = 'SUCCESS',
  FAILURE = 'FAILURE'
}
import { logger } from '../utils/logger';

export interface AuditContext {
  type?: AuditLogType;
  resourceId?: string;
  resourceType?: string;
  details?: Record<string, unknown>;
}

/**
 * 扩展Request以包含审计上下文
 */
export interface AuditRequest extends AuthenticatedRequest {
  auditContext?: AuditContext;
  startTime?: number;
}

/**
 * 记录请求完成
 */
function logRequestCompletion(req: AuditRequest, res: Response) {
  const responseTime = req.startTime ? Date.now() - req.startTime : 0;
  
  if (!req.user) {
    return;
  }
  
  const context = req.auditContext || {};
  
  AuditLogService.create({
    type: context.type || AuditLogType.USER_LOGIN,
    userId: req.user._id,
    details: {
      method: req.method,
      path: req.path,
      query: req.query,
      body: req.method !== 'GET' ? req.body : undefined,
      status: res.statusCode,
      responseTime,
      ...context.details
    },
    resourceId: context.resourceId,
    resourceType: context.resourceType,
    status: res.statusCode >= 400 ? AuditLogStatus.FAILURE : AuditLogStatus.SUCCESS,
    ip: req.ip,
    userAgent: req.get('user-agent')
  }).catch(error => {
    logger.error('Failed to create audit log', { error });
  });
}

/**
 * 审计日志中间件
 */
export function auditMiddleware(defaultType: AuditLogType = AuditLogType.USER_LOGIN) {
  return (req: Request, res: Response, next: NextFunction) => {
    const auditReq = req as AuditRequest;
    auditReq.startTime = Date.now();
    
    // 设置默认的审计上下文
    if (!auditReq.auditContext) {
      auditReq.auditContext = { type: defaultType };
    }

    // 响应完成时记录日志
    res.on('finish', () => {
      logRequestCompletion(auditReq, res);
    });

    // 响应关闭时记录日志（处理错误情况）
    res.on('close', () => {
      if (!res.writableEnded) {
        logRequestCompletion(auditReq, res);
      }
    });
    
    next();
  };
}

/**
 * 为请求设置审计上下文
 */
export function setAuditContext(
  req: Request,
  context: AuditContext
) {
  const auditReq = req as AuditRequest;
  auditReq.auditContext = {
    ...auditReq.auditContext,
    ...context
  };
}

/**
 * 创建审计包装器
 */
export function withAudit<T extends (...args: any[]) => Promise<any>>(
  handler: T,
  type: AuditLogType,
  getResourceInfo?: (req: AuditRequest, ...args: any[]) => { id?: string; type?: string }
): T {
  return (async (req: AuditRequest, ...args: any[]) => {
    try {
      const resourceInfo = getResourceInfo?.(req, ...args);
      
      setAuditContext(req, {
        type,
        resourceId: resourceInfo?.id,
        resourceType: resourceInfo?.type
      });
      
      return await handler(req, ...args);
    } catch (error) {
      // 在错误发生时更新审计上下文
      setAuditContext(req, {
        type: AuditLogType.SYSTEM_ERROR,
        details: {
          error: error instanceof Error ? error.message : String(error),
          stack: error instanceof Error ? error.stack : undefined
        }
      });
      throw error;
    }
  }) as T;
}

/**
 * 通用审计中间件工厂
 */
export const audit = {
  // 记录访问
  access: auditMiddleware(AuditLogType.USER_LOGIN),
  
  // 记录认证
  auth: auditMiddleware(AuditLogType.USER_LOGIN),
  
  // 记录创建操作
  create: (resourceType: string) => auditMiddleware(AuditLogType.USER_CREATE),
  
  // 记录更新操作
  update: (resourceType: string) => auditMiddleware(AuditLogType.USER_UPDATE),
  
  // 记录删除操作
  delete: (resourceType: string) => auditMiddleware(AuditLogType.USER_DELETE),
  
  // 记录系统操作
  system: auditMiddleware(AuditLogType.SYSTEM_ERROR),

  // 自定义类型
  custom: (type: AuditLogType) => auditMiddleware(type)
};
